import { useEffect } from "react";
import { LocationDescriptor } from "history";
import { useHistory as useHistoryRouter, useLocation } from "react-router";
type History = ReturnType<typeof useHistoryRouter>;
type Location = ReturnType<typeof useLocation>;
type Listen = (form: Location, to: Location, next: Next) => void;
interface Next {
    (): void;
    (path: string, state?: unknown): void;
    (location: LocationDescriptor<unknown>): void;
}
interface MyHistory extends History {
    beforeEach: (listen: Listen) => void;
}
let currentListen: Listen = () => {};
const createNext = function (
    this: History,
    rewritePush: (a: any, b?: any) => void,
    arg1: any,
    arg2?: any
): Next {
    const target = this;
    return function (p1?: any, p2?: any) {
        if (arguments.length === 0) {
            if (typeof arg1 === "string") {
                if (arg1 === location.pathname) return;
                target.push(arg1, arg2);
            } else if (typeof arg1 === "object") {
                if (arg1.pathname === location.pathname) return;
                target.push(arg1);
            }
        } else if (typeof p1 === "string") {
            rewritePush(arg1, p2);
        } else if (typeof p1 === "object") {
            rewritePush(p1);
        }
    };
};
const beforeEach = (listen: Listen) => {
    currentListen = listen;
};
const createProxyHandlers = function (
    history: History,
    location: Location,
    push: (...args: any[]) => void
) {
    return {
        get(target: History, key: string, receiver: any) {
            if (key === "push") {
                return push;
            }
            if (key === "beforeEach") {
                return beforeEach;
            }
            return Reflect.get(target, key, receiver);
        },
    };
};

export default function useHistory() {
    const historyRouter = useHistoryRouter();
    const location = useLocation();
    function pushFunc(arg1: any, arg2?: any) {
        const next: Next = createNext.call(historyRouter, pushFunc, arg1, arg2);
        currentListen(
            location,
            { pathname: arg1, state: arg2 } as Location,
            next
        );
    }
    useEffect(() => {
        currentListen(
            null as any,
            location,
            createNext.call(historyRouter, pushFunc, location)
        );
    }, []);
    const myHistory: MyHistory = new Proxy(
        historyRouter,
        createProxyHandlers(historyRouter, location, pushFunc)
    ) as MyHistory;
    return myHistory;
}
